package texture;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class StitcherStatic extends Stitcher {

	public StitcherStatic(int maxWidth, int maxHeight, boolean forcePowerOf2) {
		this(maxWidth, maxHeight, forcePowerOf2, 0);
	}

	public StitcherStatic(int maxWidth, int maxHeight, boolean forcePowerOf2, int maxTileDimension) {
		super(maxWidth, maxHeight, forcePowerOf2, maxTileDimension);
	}

	public void doStitch() {
		StitchHolder[] arrayStitchholder = (StitchHolder[]) this.setStitchHolders.toArray(new StitchHolder[this.setStitchHolders.size()]);
		Arrays.sort(arrayStitchholder);
		int len = arrayStitchholder.length;

		for (int i = 0; i < len; ++i) {
			StitchHolder stitchholder = arrayStitchholder[i];
			if (!this.allocateSlot(stitchholder)) {
				throw new StitcherException(stitchholder, populateMsgSizeNotFit(stitchholder));
			}
		}

		if (this.forcePowerOf2) {
			this.currentWidth = this.getCeilPowerOf2(this.currentWidth);
			this.currentHeight = this.getCeilPowerOf2(this.currentHeight);
		}
	}

	private boolean allocateSlot(StitchHolder stitchHolder) {
		for (int i = 0; i < this.stitchSlots.size(); ++i) {
			if ((this.stitchSlots.get(i)).addSlot(stitchHolder)) {
				return true;
			}

			stitchHolder.rotate();

			if (((StitchSlot) this.stitchSlots.get(i)).addSlot(stitchHolder)) {
				return true;
			}

			stitchHolder.rotate();
		}

		return this.expandAndAllocateSlot(stitchHolder);
	}

	private boolean expandAndAllocateSlot(StitchHolder stitchHolder) {
		int i = Math.min(stitchHolder.getHeight(), stitchHolder.getWidth());
		boolean flag = this.currentWidth == 0 && this.currentHeight == 0;
		boolean flag1;

		if (this.forcePowerOf2) {
			int j = this.getCeilPowerOf2(this.currentWidth);
			int k = this.getCeilPowerOf2(this.currentHeight);

			int l = this.getCeilPowerOf2(this.currentWidth + i);
			int i1 = this.getCeilPowerOf2(this.currentHeight + i);

			boolean flag2 = l <= this.maxWidth;
			boolean flag3 = i1 <= this.maxHeight;

			if (!flag2 && !flag3) {// not expandable
				return false;
			}

			int j1 = Math.max(stitchHolder.getHeight(), stitchHolder.getWidth());

			if (flag && !flag2 && this.getCeilPowerOf2(this.currentHeight + j1) > this.maxHeight) {
				return false;
			}

			boolean flag4 = j != l;
			boolean flag5 = k != i1;

			if (flag4 ^ flag5) {
				flag1 = flag5 && flag3; // Forge: Bug fix: Attempt to fill all downward space before expanding width
			} else {
				flag1 = flag2 && j <= k;
			}
		} else {
			boolean flag6 = this.currentWidth + i <= this.maxWidth;
			boolean flag7 = this.currentHeight + i <= this.maxHeight;

			if (!flag6 && !flag7) {
				return false;
			}

			flag1 = (flag || this.currentWidth <= this.currentHeight) && flag6;
		}

		StitchSlot stitchslot;

		if (flag1) {
			if (stitchHolder.getWidth() > stitchHolder.getHeight()) {
				stitchHolder.rotate();
			}

			if (this.currentHeight == 0) {
				this.currentHeight = stitchHolder.getHeight();
			}

			stitchslot = new StitchSlot(this.currentWidth, 0, stitchHolder.getWidth(), this.currentHeight);
			this.currentWidth += stitchHolder.getWidth();
		} else {
			stitchslot = new StitchSlot(0, this.currentHeight, this.currentWidth, stitchHolder.getHeight());
			this.currentHeight += stitchHolder.getHeight();
		}

		stitchslot.addSlot(stitchHolder);
		this.stitchSlots.add(stitchslot);
		return true;
	}

	private int getCeilPowerOf2(int par1) {
		int j = par1 - 1;
		j |= j >> 1;
		j |= j >> 2;
		j |= j >> 4;
		j |= j >> 8;
		j |= j >> 16;
		return j + 1;
	}

	public List<TextureAtlasSprite> getStichSlots() {
		ArrayList<StitchSlot> arraylist = new ArrayList<>();
		Iterator<StitchSlot> iterator = this.stitchSlots.iterator();

		while (iterator.hasNext()) {
			StitchSlot stitchslot = iterator.next();
			stitchslot.getAllStitchSlots(arraylist);
		}

		ArrayList<TextureAtlasSprite> arraylist1 = new ArrayList<>();
		Iterator<StitchSlot> iterator1 = arraylist.iterator();

		while (iterator1.hasNext()) {
			StitchSlot stitchslot1 = iterator1.next();
			StitchHolder stitchholder = stitchslot1.getStitchHolder();

			TextureAtlasSprite textureatlassprite = stitchholder.getAtlasSprite();
			textureatlassprite.initSprite(this.currentWidth, this.currentHeight, stitchslot1.getOriginX(), stitchslot1.getOriginY(), stitchholder.isRotated());
			arraylist1.add(textureatlassprite);
		}

		return arraylist1;
	}

	private String populateMsgSizeNotFit(StitchHolder stitchholder) {
		String msgTemplate = "Unable to fit: %s - size: %dx%d - Maybe try a lowerresolution texturepack?";
		String iconName = stitchholder.getAtlasSprite().getIconName();
		Integer iconWidth = Integer.valueOf(stitchholder.getAtlasSprite().getIconWidth());
		Integer iconHeight = Integer.valueOf(stitchholder.getAtlasSprite().getIconHeight());
		return String.format(msgTemplate, new Object[] { iconName, iconWidth, iconHeight });
	}
}
